﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace MenuLib
{
    [Serializable]
    public class MenuItemCollection : IList<MenuItem>, ISerializable
    {
        public MenuItemCollection(Menu owner)
        {
            this.owner = owner;
            itemList = new List<MenuItem>();
        }

        public MenuItem this[string name]
        {
            get
            {
                MenuItem result = itemList.Find(item => item.Name == name);

                if (result == null)
                    throw new ApplicationException("No item with name: " + name);

                return result;
            }
        }

        public void ForEach(Action<MenuItem> action)
        {
            itemList.ForEach(action);
        }

        #region IList<MenuItem> Members

        public int IndexOf(MenuItem item)
        {
            return itemList.IndexOf(item);
        }

        public void Insert(int index, MenuItem item)
        {
            itemList.Insert(index, item);

            OnItemAdded(item);
        }

        public void RemoveAt(int index)
        {
            MenuItem itemToRemove = itemList[index];

            itemList.RemoveAt(index);

            OnItemRemoved(itemToRemove);
        }

        public MenuItem this[int index]
        {
            get
            {
                return itemList[index];
            }
            set
            {
                throw new NotImplementedException("MenuItemCollection set indexer");
            }
        }

        #endregion

        #region ICollection<MenuItem> Members

        public void Add(MenuItem item)
        {
            Insert(Count, item);
        }

        void ICollection<MenuItem>.Clear()
        {
            while (Count > 0)
            {
                RemoveAt(0);
            }

            itemList.Clear();
        }

        public bool Contains(MenuItem item)
        {
            return itemList.Contains(item);
        }

        public void CopyTo(MenuItem[] array, int arrayIndex)
        {
            itemList.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return itemList.Count; }
        }

        bool ICollection<MenuItem>.IsReadOnly
        {
            get
            {
                return (itemList as ICollection<MenuItem>).IsReadOnly;
            }
        }

        public bool Remove(MenuItem item)
        {
            int index = IndexOf(item);

            if (0 <= index)
            {
                RemoveAt(index);
                return true;
            }

            return false;
        }

        #endregion

        #region IEnumerable<MenuItem> Members

        public IEnumerator<MenuItem> GetEnumerator()
        {
            return itemList.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (itemList as IEnumerable).GetEnumerator();
        }

        #endregion

        #region ISerializable Members

        const string ownerValueName = "Owner";
        const string itemListValueName = "ItemList";

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(ownerValueName, owner);
            info.AddValue(itemListValueName, itemList);
        }

        protected MenuItemCollection(SerializationInfo info, StreamingContext context)
        {
            owner = (Menu)info.GetValue(ownerValueName, typeof(Menu));
            itemList = (List<MenuItem>)info.GetValue(
                itemListValueName, typeof(List<MenuItem>));
        }

        #endregion

        protected virtual void OnItemAdded(MenuItem item)
        {
            owner.ItemAdded(item);
        }

        protected virtual void OnItemRemoved(MenuItem item)
        {
            owner.ItemRemoved(item);
        }

        private Menu owner;
        private List<MenuItem> itemList;
    }
}
